#include "xlcomm/net/tcp_server.h"

#include <signal.h>

#include <iostream>

using namespace xlcomm;

#define BOOST_TEST_MAIN
#define BOOST_TEST_DYN_LINK
#include "boost/test/unit_test.hpp"

void ShowDetail(const net::Buffer& buff) {
  std::cout << "PrependableBytes:" << buff.PrependableBytes()
            << " ReadableBytes:" << buff.ReadableBytes()
            << " WritableBytes:" << buff.WritableBytes()
            << " Size:" << buff.Size()
            << " reader_index:" << buff.reader_index()
            << " writer_index:" << buff.writer_index() << std::endl;
}

BOOST_AUTO_TEST_CASE(Buffer) {
  std::cout << "-------------Buffer\n";
  net::Buffer buff;
  char data[] = "hello";  // 5byte
  int len = strlen(data);
  buff.Append(data, len);
  buff.PrependInt32ToNet(len);      // 4byte
  buff.PrependInt16ToNet(len - 1);  // 2byte
  ShowDetail(buff);
  std::cout << buff.PeekInt16ToHost() << buff.ReadInt16ToHost()
            << buff.ReadInt32ToHost() << std::endl;
  ShowDetail(buff);
  std::cout << "Shrink\n";
  buff.Shrink(4);
  ShowDetail(buff);
  std::cout << buff.ReadAllAsString() << std::endl;
  ShowDetail(buff);
}

void OnOutbufHighWater(const net::TcpConnectionPtr& conn, size_t remain_bytes) {
  std::cout << __FUNCTION__ << "----remain_bytes:" << remain_bytes << " ";
  std::cout << "暂停获取上游数据" << std::endl;
}

void OnConnect(const net::TcpConnectionPtr& conn) {
  std::cout << __FUNCTION__ << "----peer:" << conn->peer_addr().ToIpPort()
            << std::endl;
  conn->SetOutbufHighWaterMark(OnOutbufHighWater, 10);
  conn->Send("hello connection\n");
  // conn->Shutdown();  // ::shutdown(SHUT_WR)后再::write会收到SIGPIPE信号
}

void OnDisConnect(const net::TcpConnectionPtr& conn) {
  std::cout << __FUNCTION__ << "----peer:" << conn->peer_addr().ToIpPort()
            << std::endl;
}

void OnMessage(const net::TcpConnectionPtr& conn, net::Buffer* buffer,
               Timestamp recv_time) {
  std::cout << __FUNCTION__ << "----received " << buffer->ReadableBytes()
            << " bytes from " << conn->name() << " at "
            << DateTime::Format(recv_time) << std::endl;
  std::cout << __FUNCTION__ << "----message:" << buffer->ReadAllAsString()
            << std::endl;
  std::this_thread::sleep_for(std::chrono::seconds(2));
  // 如果此时客户端意外崩溃
  conn->Send("hello message1\n");  // 第一次::write发消息会收到RST packet
  conn->Send("hello message2\n");  // 第二次::write发消息就会收到SIGPIPE信号
  // 在网络编程中经常会遇到SIGPIPE信号，默认情况下这个信号会终止整个进程
}

void OnWriteComplete(const net::TcpConnectionPtr& conn) {
  std::cout << __FUNCTION__ << "----" << std::endl;
  // std::cout << "继续获取上游数据" << std::endl;
}

BOOST_AUTO_TEST_CASE(TcpServer) {
  std::cout << "-------------TcpServer\n";
  ::signal(SIGPIPE, SIG_IGN);  // 忽略SIGPIPE信号

  Logger::SetLogLevel(Logger::kDebug);
  net::EventLoop loop;

  net::TcpServer server(&loop, net::InetAddress(4444), "tcp_server_test",
                        net::TcpServer::kReusePort);
  server.set_connect_callback(OnConnect);
  server.set_disconnect_callback(OnDisConnect);
  server.set_message_callback(OnMessage);
  server.set_write_complete_callback(OnWriteComplete);
  server.Start(2);

  // net::TcpServer server2(&loop, net::InetAddress(5555), "tcp_server_test2",
  //                        net::TcpServer::kReusePort);
  // server2.Start(0);

  loop.Loop();
}